
#ifndef PARALLEL_H
#define PARALLEL_H

#include <pthread.h>
#include <netinet/in.h>
#ifdef SOLARIS_4_GTK
#include <sys/file.h>
#endif

/* A magic number we identify valid traffic with */
#define MAGIC 					0x72fe2434
/* jhat */
extern char clientIP[];

#define DAEMON_PORT    			4000

/* These are the messages a daemon sends to the fpc client */
#define DAEMON_WANTS_TO_QUIT	0x00000000
#define DAEMON_WANTS_CLONES		0x00000001
#define DAEMON_DONE_CLONE		0x00000002
#define DAEMON_REPORTING_ERROR	0x00000003
#define DAEMON_KEEP_ALIVE_PING	0x00000004
#define DAEMON_HERE_ARE_CLONES	0x00000005

/* DAEMON_WANTS_CLONE is followed by:
 *   <number of clones to do in a batch>
 * DAEMON_DONE_CLONE is followed by:
 *   <clone #>
 *   <# of nodes added to sparse matrix>
 *   { <clone#> <exponent> <match> }
 */
 
/* The fpc client sends:
 *   in response to DAEMON_WANTS_TO_QUIT:
 *	closes connection
 *   in response to DAEMON_WANTS_CLONES:
 *	an array of clone#s of size = the number of clones requested
 *	a zero in the list denotes that we've run out of clones.
 *   in response to DAEMON_DONE_CLONE:
 *	nill
 */

/* Number of jobs completed thus far */
extern long long int jobCount;

/************** Functions *************/

int initMutexes();
int destroyMutexes();

/* Status values passed to acquireWorkerOrders */
#define STATUS_OK				0
#define STATUS_FAIL_ALGORITHM	-1 /* Non-recoverable */
#define STATUS_FAIL_NETWORK		-2 /* Usually recoverable */
#define STATUS_RETURNING_ORDER	-3 /* Not an error :-) */

/* Obtains orders from the dispatcher (whichever is running) */
int acquireWorkerOrders(int lastStatus);

struct daemonPusherArg
{
	int                 daemonCount;
	int*                daemons;
    struct sockaddr_in* daemon_sins;
};

/* Lookups up the FQDN of the given host */
const char* addressToName(struct sockaddr_in addr);

/* The void* argument is not used. Returned: STATUS_* as defined above */
void* localWorkerProcedure(void* arg);

/* The void* argument is really type struct daemonPusherArg* */
/* Retuned: STATUS_* as defined above */
void* daemonPusherProcedure(void* arg);

/* Returns the number of daemons found and allocates dynamic memory
 * for the passed pointers. The first is a vector of sockets, the second
 * is a vector of addresses.
 */
int findDaemons(int** daemonOut, struct sockaddr_in** addrOut);

/* These functions return the number of cache misses (>= 0) on success.
 * On error they return one of the STATUS_FAIL values above
 */
int localDispatcherProcedure(int numberThreads, int queueHead);
int slaveDispatcherProcedure(int threadCount, int sock, pthread_mutex_t* mutex);

int parallel_node_creation();
 
#endif
